package com.culture.config.service.impl;

import java.util.Objects;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import com.culture.config.common.util.BeanUtil;
import com.culture.config.common.util.ExceptionUtil;
import com.culture.config.component.RestTemplateEx;
import com.culture.config.dao.entity.*;
import com.culture.config.dao.mapper.*;
import com.culture.config.model.po.*;
import com.culture.config.model.vo.*;
import com.culture.config.service.InstanceService;
import com.culture.config.wrapper.AppInstanceWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class InstanceServiceImpl implements InstanceService {
    @Resource
	private AppMapper appMapper;
    @Resource
	private AppInstanceMapper appInstanceMapper;
	@Autowired
	private RestTemplateEx restTemplateEx;

    @Override
	public RegistrationVO register(RegistrationPO param) {
        log.info("register:{}",param);
		App app = this.appMapper.getByName(param.getName());	
		AppInstance registerApp = AppInstanceWrapper.wrapAppInstanceRegister(param,app);
		AppInstance oldInstance = this.appInstanceMapper.getByName(registerApp);
		if(Objects.nonNull(oldInstance)){
			this.appInstanceMapper.update(AppInstanceWrapper.wrapAppInstanceHeartbeat(oldInstance,param));
			return AppInstanceWrapper.wrapRegistrationVO(oldInstance);
		}
		this.appInstanceMapper.add(registerApp);
		return AppInstanceWrapper.wrapRegistrationVO(registerApp);
	}

	@Override
	public void unRegister(String id) {
        log.info("unRegister:{}",id);
		AppInstance appInstance = this.appInstanceMapper.get(Long.valueOf(id));
		if(Objects.isNull(appInstance)){
			return;
		}		
		this.appInstanceMapper.update(AppInstanceWrapper.wrapAppInstanceUnregister(id));
	}

	@Override
	public void heartbeat(String id) {
        log.info("heartbeat:{}",id);
		AppInstance appInstance = this.appInstanceMapper.get(Long.valueOf(id));
		if(Objects.isNull(appInstance)){
			return;
		}		
		this.appInstanceMapper.update(AppInstanceWrapper.wrapAppInstanceHeartbeat(id));
	}	

    @Override
    public Page<AppInstanceVO> page(AppInstancePagePO appInstancePagePO) {
        PageMethod.startPage(appInstancePagePO.getPageNum(),appInstancePagePO.getPageSize());
        Page<AppInstance> pAppInstances = this.appInstanceMapper.page(AppInstanceWrapper.wrapAppInstanceQuery(appInstancePagePO));
        if(CollectionUtils.isEmpty(pAppInstances)){
            return new Page<>();
        }
        return BeanUtil.copyPageProperties(pAppInstances, AppInstanceVO.class,  AppInstanceWrapper::wrapAppInstancePage);
	}

	@Override
	@SuppressWarnings("unchecked")
	public AppInstanceProxyVO proxy(AppInstanceProxyPO appInstanceProxyPO) {
        log.info("proxy:{}",appInstanceProxyPO);
		AppInstance appInstance = this.appInstanceMapper.get(appInstanceProxyPO.getId());
		ExceptionUtil.businessExceptionWhenNull(appInstance, "AppInstance can't be found.");
		String proxyUrl = StringUtils.join(appInstance.getManagementUrl(), appInstanceProxyPO.getPath());
		Map<String,Object> proxyResult = this.restTemplateEx.action(appInstanceProxyPO.getMethod(), proxyUrl, appInstanceProxyPO.getProxyParms(), Map.class);
		return AppInstanceWrapper.wrapAppInstanceProxyVO(appInstance,proxyResult);
	}

	@Override
	public void refreshConfiguration(PropertyRefreshPO refreshPO) {
		List<AppInstance> appInstanceList = this.appInstanceMapper.listByAppId(refreshPO.getAppId());
		if(CollectionUtils.isEmpty(appInstanceList)){
			return;
		}
		appInstanceList.forEach(appInstance->{
			String proxyUrl = StringUtils.join(appInstance.getManagementUrl(), "/refresh");
			String result = this.restTemplateEx.action("POST", proxyUrl, null, String.class);
			log.info("refreshConfiguration:{}",result);
		});
	}

	@Override
	public void refreshConfiguration(AppInstanceRefreshPO refreshPO) {
		AppInstance appInstance = this.appInstanceMapper.get(refreshPO.getId());
		if(Objects.isNull(appInstance)){
			return;
		}
		String proxyUrl = StringUtils.join(appInstance.getManagementUrl(), "/refresh");
		String result = this.restTemplateEx.action("POST", proxyUrl, null, String.class);
		log.info("refreshConfiguration:{}",result);
	}

}
